iT邦幫忙

2021 iThome 鐵人賽

DAY 4
0

講完了怎麼取 tag 的值,我們來取 tag 夾帶的屬性。假設我們拿到了下面的 RSS 內容:

<channel>	
      <category>channel category 1</category>
      <category domain="http://channel.category.domain">channel category 2</category>
</channel>

首先我們先取 <category> 的 attribute ,但我們在處理 parser 的時候有個基本原則就是不能夠預設資料一定存在,所以 null safty 處理在這邊是需要非常小心!對 Element 取值只要用原生的 function getAttribute 就好了。

fun Element.getAttributeOrNull(tag: String): String? {
    val attr = getAttribute(tag) ?: return null
    return if (attr.isEmpty() || attr.isBlank()) null else attr
}

接著我們可以來處理怎麼拿到 <category> 的資訊,上面的情況我們拿到讀 category 不只一個,而且內容物不一定相同。我可以自己定義一個 data class 去包這些資訊,但他內含的資訊有可能是 nullable 的。

data class Category(
    val name: String?,
    val domain: String?,
)

之後我們就可以把上面的東西整合一下,寫出一個專門讀 <category> 列表的 extension function 。

fun Element.readCategories(parentTag: String, tagName: String): List<Category>? {
    val result = mutableListOf<Category>()
    val nodeList = getElementsByTagName(tagName) ?: return null

    for (i in 0 until nodeList.length) {
        val e = nodeList.item(i) as? Element ?: continue
        val parent = e.parentNode as? DeferredElementImpl
        if (parent?.tagName == parentTag || parent?.tagName == tagName) {
            result.add(Category(name = e.getAttributeOrNull(TEXT), domain = null))
        }
    }
    return result
}

那上面為什麼又需要 parentTag 呢?因為 category 這個 tag 有可能存在在其他的子節點裡,比方說像下面這樣:

<channel>
		<category>channel category 1</category>
        <category domain="http://channel.category.domain">channel category 2</category>
		<item>
            <category>item category 1</category>
		</item>
		<item>
            <category>item category 2</category>
		</item>
</channel>

總結一下目前我們寫的 Custom DOM Parser 做的事情:

  1. 取某個 tag 的 value 。
  2. 取某個 tag 的 attribute 。
  3. 跨層搜尋某個 tag 。
  4. 抓取 tag 底下的 value 和 attribute ,像是上面的 category 列表。

現在這種實作方式,每遇到一種樣子的 tag ,我們就有可能需要多寫一個 function 和多定義一個 data class 去包裡面的資訊。Kotlin 的實作方式可以讓我們在有支援 Kotlin 的平台上,去操作這些 parser ,但我們也可以透過平台專屬的 API 去優化我們的 parser ,下篇文章我們就會開始以 Android 為例去優化我們的 Kotlin parser 。


上一篇
使用 DOM Parser 取值
下一篇
Android XML Parser
系列文
如何使用 Kotlin Annotation Processor 做出自己的 Custom Data Parser Library30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言